package com.generalaj.console.builder;

import com.generalaj.console.compress.tar.ZipCreator;
import com.generalaj.console.configuration.workflow.GraphParser;
import com.generalaj.console.configuration.workflow.GraphManager;
import com.generalaj.console.configuration.workflow.GraphNode;
import com.generalaj.io.util.IOUtil;
import org.beetl.core.Template;

import java.io.*;
import java.util.*;

/**
 * Created by wangxin on 2017/2/24.
 */
public class AzkabanResourcesBuilder {


    private TemplatesTools templatesTools;
    private Map<String,String> commonConfig;
    private String envConfigPath;

    public AzkabanResourcesBuilder(String envConfig) throws IOException {
        this.envConfigPath=envConfig;
        Properties prop=new Properties();
        prop.load(new FileInputStream(envConfig));
        commonConfig=new HashMap<String, String>();
        for(Object key:prop.keySet()){
            String value=prop.getProperty((String)key);
            commonConfig.put((String)key,value);
        }

    }

    /**
     * 1. create workspace
     * 2. copy static resource
     * 3. copy user's files
     * 4. list all workflow config file
     * 5. for..each parse  workflow config
     * 6. for..each craete job's dir
     * In params:
     *  root:generated root dir,
     *  src:resource root dir,
     *  userDirPath:user's resource root dir,
     *  templateDir:templates root dir
     * throws IOException
     */
    public void build(String root,String src,String userDirPath,String templateDir) throws IOException {
        String originalDirName="original";
        File workspace=new File(root);
        craeteWorkspace(root);
        copyResource(root,src);
        copyResource(root+File.separator+originalDirName,userDirPath);
        templatesTools =new TemplatesTools();
        templatesTools.init(templateDir);
        List<File> list=listWorkflow(root+File.separator+originalDirName);

        for(File f:list){
            GraphManager maker=parserWorkflowConfig(f);
            Set<GraphNode> jobs=maker.getAllNodes();
            String dependency=null;
            for(GraphNode job : jobs){
                if(!job.getType().equals("root")){
                    String jobName=job.getName();
                    File jobDir=new File(workspace,jobName);
                    dependency="";
                    Set<GraphNode> dependencyNodes=maker.getDependencies(job);
                    for(GraphNode dependencyNode:dependencyNodes){
                        String name=dependencyNode.getName();
                        dependency+=name;
                        dependency+=",";
                    }
                    dependency=dependency.substring(0,dependency.length()-1);
                    String jobFilePath = root + File.separator + originalDirName + File.separator + job.getName() + ".txt";
                    if(job.getType().equals("init")){
                        createInitWorkspaceDir(jobName,jobDir);
                    }else if(job.getType().equals("hive")){
                        createHiveDir(job,jobDir, jobFilePath,dependency);
                    }else if(job.getType().equals("sqlserver")){
                        createSqlServerDir(job,jobDir,jobFilePath,dependency);
                    }else if(job.getType().equals("sqoop-export")){
                        createSqoopExportDir(job,jobDir,jobFilePath,dependency);
                    }else if(job.getType().equals("sqoop-import")){
                        createSqoopImportDir(job,jobDir,jobFilePath,dependency);
                    }
                }
            }

        }
        copyCommonProptiesFile(workspace);
    }

    private void copyCommonProptiesFile(File dir) throws IOException {
        IOUtil.copyTxtFile(new File(envConfigPath),new File(dir,"common.properties"));
    }

    private void createSqoopImportDir(GraphNode job, File dir, String jobFilePath, String dependency) throws IOException {
        dir.mkdir();
        Template tpl=templatesTools.getTemplate("sqoop_import/job.template");
        tpl.binding("depends",dependency);
        tpl.binding(commonConfig);
        tpl.binding(job.getConfig());
        File jobFile=new File(dir,job.getName()+".job");
        Writer writer=new FileWriter(jobFile);
        try{
            tpl.renderTo(writer);
        }finally {
            writer.close();
        }
        Template tpl1=templatesTools.getTemplate("sqoop_import/run_sqoop_import.sh");
        tpl1.binding(commonConfig);
        tpl1.binding(job.getConfig());
        File jobFile1=new File(dir,"run_sqoop_import.sh");
        Writer writer1=new FileWriter(jobFile1);
        try{
            tpl1.renderTo(writer1);
        }finally {
            writer1.close();
        }
    }

    private void createSqoopExportDir(GraphNode job, File dir, String jobFilePath, String dependency) throws IOException {
        dir.mkdir();
        Template tpl=templatesTools.getTemplate("sqoop_export/job.template");
        tpl.binding("depends",dependency);
        tpl.binding(commonConfig);
        tpl.binding(job.getConfig());
        File jobFile=new File(dir,job.getName()+".job");
        Writer writer=new FileWriter(jobFile);
        try{
            tpl.renderTo(writer);
        }finally {
            writer.close();
        }
        Template tpl1=templatesTools.getTemplate("sqoop_export/run_sqoop_export.sh");
        tpl1.binding(commonConfig);
        tpl1.binding(job.getConfig());
        File jobFile1=new File(dir,"run_sqoop_export.sh");
        Writer writer1=new FileWriter(jobFile1);
        try{
            tpl1.renderTo(writer1);
        }finally {
            writer1.close();
        }
    }

    
    /**
     *
     * @param job the job's name
     * @param dir the generated job dir's name
     * @param jobFilePath user's file
     * @param dependsStr the dependencies jobs flatted string, such as "job1,job2,job3".
     * @throws IOException
     */
    public void createHiveDir(GraphNode job,File dir,String jobFilePath,String dependsStr) throws IOException {
        dir.mkdir();
        IOUtil.copyTxtFile(new File(jobFilePath),new File(dir,"job.txt"));
        Template tpl=templatesTools.getTemplate("hive/job.template");
        tpl.binding("depends",dependsStr);
        tpl.binding(job.getConfig());
        File jobFile=new File(dir,job.getName()+".job");
        Writer writer=new FileWriter(jobFile);
        try{
            tpl.renderTo(writer);
        }finally {
            writer.close();
        }
    }

    /**
     *
     * @param job the job's name
     * @param dir the generated job dir's name
     * @param jobFilePath user's file
     * @param dependsStr the dependencies jobs flatted string, such as "job1,job2,job3".
     * @throws IOException
     */
    public void createSqlServerDir(GraphNode job,File dir,String jobFilePath,String dependsStr) throws IOException {
        dir.mkdir();
        IOUtil.copyTxtFile(new File(jobFilePath),new File(dir,"job.txt"));
        Template tpl=templatesTools.getTemplate("sqlserver/job.template");
        tpl.binding("depends",dependsStr);
        tpl.binding(job.getConfig());
        File jobFile=new File(dir,job.getName()+".job");
        Writer writer=new FileWriter(jobFile);
        try{
            tpl.renderTo(writer);
        }finally {
            writer.close();
        }
    }


    public void createInitWorkspaceDir(String jobName,File dir) throws IOException {
        dir.mkdir();
        IOUtil.copyTxtFile(templatesTools.getInitWorkspaceTemplate(),new File(dir,jobName+".job"));
    }

    public void craeteWorkspace(String root){
        File workspace=new File(root);
        workspace.mkdirs();
    }
    public void copyResource(String root,String src) throws IOException {
        File resourceDir=new File(src);
        File rootDir=new File(root);
        IOUtil.copyTxtDirectory(resourceDir,rootDir);
    }
    public List<File> listWorkflow(String root){
        File rootDir=new File(root);
        File[] originals=rootDir.listFiles();
        List<File> results=new ArrayList<File>();
        for(File f:originals){
            if(f.getName().endsWith(".wf")){
                results.add(f);
            }
        }
        return results;
    }
    public static GraphManager parserWorkflowConfig(File workflowConfig) throws IOException {
        GraphParser config=new GraphParser();
        config.parseGraphConfig(workflowConfig);
        return config.getMaker();
    }

    /**
     *
     * @param zipFilePath zip boll path
     * @param buildSpace build the zip's dir
     * @param resourceDir static resource dir
     * @param userDirPath user's resource dir
     * @param templateDir templates resource dir
     * @return the zip boll path
     * @throws IOException
     */
    public String createZipPackage(String zipFilePath,String buildSpace,String resourceDir,String userDirPath,String templateDir) throws IOException {
        build(buildSpace,resourceDir,userDirPath,templateDir);
        File zipFile=new File(zipFilePath);
        if(zipFile.exists()){
            zipFile.delete();
        }
        ZipCreator zip=new ZipCreator(zipFile);
        zip.inflate(new File(buildSpace));
        return zipFilePath;
    }

}
